package znet

import (
	"errors"
	log "github.com/cihub/seelog"

	//"github.com/aceld/zinx/zlog"
	"sync"
	"time"

	"github.com/aceld/zinx/ziface"
)

//ConnManager 连接管理模块
type ConnManager struct {
	connections map[uint32]ziface.IConnection //管理的连接信息
	connLock    sync.RWMutex                  //读写连接的读写锁
}


func CreateTicker(interval int64, doJob func()) {
	// 启动个定时器
	ticker := time.NewTicker(time.Duration(interval) * time.Millisecond)

	done := make(chan bool)
	go func() {
		for {
			select {
			case <-done:
				return
			case <-ticker.C:
				doJob()
			}
		}
	}()
}
//NewConnManager 创建一个链接管理
func NewConnManager() *ConnManager {

	connManager := &ConnManager{
		connections: make(map[uint32]ziface.IConnection),
	}
	CreateTicker(60000,connManager.checkDevicesTimeOut)
	return connManager
}

//Add 添加链接
func (connMgr *ConnManager) Add(conn ziface.IConnection) {
	//保护共享资源Map 加写锁
	log.Debug("connMgrAdd")
	connMgr.connLock.Lock()
	defer connMgr.connLock.Unlock()

	//将conn连接添加到ConnMananger中
	connMgr.connections[conn.GetConnID()] = conn

	log.Debug("connection add to ConnManager successfully: conn num = ", connMgr.Len())
}

//Remove 删除连接
func (connMgr *ConnManager) Remove(conn ziface.IConnection) {
	//保护共享资源Map 加写锁
	log.Debug("connMgrRemove")
	connMgr.connLock.Lock()
	defer connMgr.connLock.Unlock()

	//删除连接信息
	delete(connMgr.connections, conn.GetConnID())

	log.Debug("connection Remove ConnID=", conn.GetConnID(), " successfully: conn num = ", connMgr.Len())
}

//Get 利用ConnID获取链接
func (connMgr *ConnManager) Get(connID uint32) (ziface.IConnection, error) {
	//保护共享资源Map 加读锁
	log.Debug("connMgrGet")
	connMgr.connLock.RLock()
	defer connMgr.connLock.RUnlock()

	if conn, ok := connMgr.connections[connID]; ok {
		return conn, nil
	}

	return nil, errors.New("connection not found")

}

//Len 获取当前连接
func (connMgr *ConnManager) Len() int {
	return len(connMgr.connections)
}

//ClearConn 清除并停止所有连接
func (connMgr *ConnManager) ClearConn() {
	//保护共享资源Map 加写锁
	//connMgr.connLock.Lock()
	//defer connMgr.connLock.Unlock()
	//
	////停止并删除全部的连接信息
	//for connID, conn := range connMgr.connections {
	//	//停止
	//	conn.Stop()
	//	//删除
	//	delete(connMgr.connections, connID)
	//}


	connections:=connMgr.GetAllConnes()
	for connID,conn :=range connections{
			//停止
			conn.Stop()
			connMgr.Remove(conn)
			//删除
			delete(connMgr.connections, uint32(connID))
	}

	log.Debugf("Clear All Connections successfully: conn num =  %d", connMgr.Len())
}

//ClearOneConn  利用ConnID获取一个链接 并且删除
func (connMgr *ConnManager) ClearOneConn(connID uint32) {

	connections:=connMgr.GetAllConnes()
	conn := connections[connID]
	if conn !=nil{
		conn.Stop()
		connMgr.Remove(conn)
		//删除
		delete(connMgr.connections, connID)
		log.Debugf("Clear Connections ID:   %d  %s", connID, "succeed")
		return
	}
	log.Debugf("Clear Connections ID:   %d  %s", connID, "err")
	return

	////保护共享资源Map 加写锁
	//connMgr.connLock.Lock()
	//defer connMgr.connLock.Unlock()
	//
	//if conn, ok := connMgr.connections[connID]; !ok {
	//	//停止
	//	conn.Stop()
	//	//删除
	//	delete(connMgr.connections, connID)
	//	log.Debugf("Clear Connections ID:   %d  %s", connID, "succeed")
	//	return
	//}
	//
	//log.Debugf("Clear Connections ID:   %d  %s", connID, "err")
	//return
}


//获取所有装置的信息
func (connMgr *ConnManager) GetAllConnes() []ziface.IConnection {
	log.Debug("connMgrGetAllConnest")
	connMgr.connLock.RLock()
	defer connMgr.connLock.RUnlock()

	//创建返回的device集合切片
	connes := make([]ziface.IConnection,0)

	//添加切片
	for _,v := range connMgr.connections{
		connes = append(connes,v)
	}

	return connes
}

func (connMgr *ConnManager) checkDevicesTimeOut(){


	log.Info("开始检测是否有链接超时离线\n")
	//停止并删除全部的连接信息+
	connes :=connMgr.GetAllConnes()
	for _, conn := range connes {

		if conn !=nil{
			timeLast, _ :=conn.GetProperty("lastTime")
			subM := time.Now().Sub(timeLast.(time.Time))
			if subM.Seconds() >30{//链接超过30秒还未获得装置信息就断开

				conn.Stop()
				connMgr.Remove(conn)

			}
		}

	}

}